
#include <gflags/gflags.h>
#include<gtest/gtest.h>
#include <thread>
#include <fstream>
#include <stdexcept>
#include <vector>

#include "etcd.hpp"
#include "channel.hpp"
#include "logger.hpp"
#include "base.pb.h"
#include "file.pb.h"
#include "utils.hpp"

DEFINE_bool(run_mode, false, "程序的运行模式，false-调试； true-发布；");
DEFINE_string(log_file, "", "发布模式下，用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下，用于指定日志输出等级");

DEFINE_string(etcd_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(speech_service, "/service/file_service", "服务监控根目录");

xu::ServiceChannel::ChannelPtr  channel;
std::string file_id;
std::vector<std::string> file_ids;

TEST(PutSingleFile,单文件上传)
{
    //ASSERT_EQ(Add(10,20),30);
    xu::FileService_Stub stub(channel.get());
    xu::PutSingleFileReq req;
    xu::PutSingleFileRsp* rsp = new xu::PutSingleFileRsp();
    brpc::Controller *cntl = new brpc::Controller();
    std::string body;
    ASSERT_EQ(xu::ReadFile("./Makefile",body),true);

    req.set_request_id("1111");
    req.mutable_file_data()->set_file_content(body);
    req.mutable_file_data()->set_file_name("./Makefile");
    req.mutable_file_data()->set_file_size(body.size());

    stub.PutSingleFile(cntl,&req,rsp,nullptr);
    ASSERT_EQ(cntl->Failed(),false);
    ASSERT_EQ(rsp->request_id(),"1111");
    ASSERT_EQ(rsp->success(),true);
    file_id = rsp->file_info().file_id();
}

TEST(GetSingleFile,单个文件获取)
{
    xu::FileService_Stub stub(channel.get());
    brpc::Controller *cntl = new brpc::Controller();
    xu::GetSingleFileReq req;
    xu::GetSingleFileRsp * rsp = new xu::GetSingleFileRsp();
    req.set_request_id("2222");
    req.set_file_id(file_id);
    stub.GetSingleFile(cntl,&req,rsp,nullptr);
    ASSERT_EQ(cntl->Failed(),false);
    ASSERT_EQ(rsp->request_id(),"2222");
    ASSERT_EQ(rsp->success(),true);
    std::string filename = "./" + rsp->file_data().file_id();
    std::string body = rsp->file_data().file_content();
    LOG_DEBUG("filename : {}" ,filename);
    ASSERT_EQ(xu::WriteFile(filename,body),true);
}


TEST(PutMultiFile,多文件上传)
{
    xu::FileService_Stub stub(channel.get());
    xu::PutMultiFileReq req;
    xu::PutMultiFileRsp* rsp = new xu::PutMultiFileRsp();
    brpc::Controller *cntl = new brpc::Controller();
    req.set_request_id("3333");

    xu::FileUploadData *data1 = req.add_file_data(); 
    std::string body1;
    ASSERT_EQ(xu::ReadFile("./file.pb.h",body1),true);
    data1->set_file_name("./file.pb.h");
    data1->set_file_content(body1);
    data1->set_file_size(body1.size());

    xu::FileUploadData *data2 = req.add_file_data(); 
    std::string body2;
    ASSERT_EQ(xu::ReadFile("./base.pb.h",body2),true);
    data2->set_file_name("./base.pb.h");
    data2->set_file_content(body2);
    data2->set_file_size(body2.size());

    stub.PutMultiFile(cntl,&req,rsp,nullptr);


    ASSERT_EQ(cntl->Failed(),false);
    ASSERT_EQ(rsp->request_id(),"3333");
    ASSERT_EQ(rsp->success(),true);

    for(int i = 0; i < rsp->file_info_size(); ++i)
    {
        file_ids.push_back(rsp->file_info(i).file_id());
    }
}

TEST(GetMultiFile,多文件获取)
{
    xu::FileService_Stub stub(channel.get());
    xu::GetMultiFileReq req;
    xu::GetMultiFileRsp* rsp = new xu::GetMultiFileRsp();
    brpc::Controller *cntl = new brpc::Controller();
    req.set_request_id("4444");
    for(int i = 0; i < file_ids.size(); ++i)
    {
        req.add_file_id_list(file_ids[i]);
    }
    
    stub.GetMultiFile(cntl,&req,rsp,nullptr);
    ASSERT_EQ(cntl->Failed(),false);
    ASSERT_EQ(rsp->request_id(),"4444");
    ASSERT_EQ(rsp->success(),true);

    auto map = rsp->file_data();
    for(int i = 0; i < file_ids.size(); ++i)
    {
        ASSERT_TRUE(map.find(file_ids[i]) !=  map.end());
        auto file_data = map[file_ids[i]];
        ASSERT_EQ(xu::WriteFile(file_data.file_id(),file_data.file_content()),true);
    }
}


int main(int argc, char *argv[])
{   
    google::ParseCommandLineFlags(&argc, &argv, true);
    InitLog(FLAGS_run_mode,FLAGS_log_file,FLAGS_log_level);
    testing::InitGoogleTest(&argc,argv);

    //1. 先构造Rpc信道管理对象
    auto sm = std::make_shared<xu::ServiceManage>();
    sm->AddFollow(FLAGS_speech_service);
    auto put_cb = std::bind(&xu::ServiceManage::onServiceOnline, sm.get(), std::placeholders::_1, std::placeholders::_2);
    auto del_cb = std::bind(&xu::ServiceManage::onServiceOffline, sm.get(), std::placeholders::_1, std::placeholders::_2);
    //2. 构造服务发现对象
    xu::Discovery::ptr dclient = std::make_shared<xu::Discovery>(FLAGS_etcd_host, FLAGS_base_service, put_cb, del_cb);
    //3. 通过Rpc信道管理对象，获取提供Echo服务的信道
    channel = sm->Choose(FLAGS_speech_service);
    if (!channel) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        return -1;
    }
    return RUN_ALL_TESTS();
}
